fix(worker): preserve permissions on transient token refresh failures#1481
Conversation
This comment has been minimized.
This comment has been minimized.
WalkthroughOAuth token refresh now uses typed failures, bounded retries, timeout and response classification. Account permission synchronization uses those classifications to clear permissions only for authorization failures and preserve them for transient or unrelated failures. ChangesOAuth refresh and exchange flow
Permission synchronization
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant AccountPermissionSyncer
participant ensureFreshAccountToken
participant exchangeRefreshToken
participant OAuthProvider
AccountPermissionSyncer->>ensureFreshAccountToken: refresh account token
ensureFreshAccountToken->>exchangeRefreshToken: exchange refresh token
exchangeRefreshToken->>OAuthProvider: POST OAuth token request
OAuthProvider-->>exchangeRefreshToken: token or classified error
exchangeRefreshToken-->>ensureFreshAccountToken: token or TokenRefreshError
ensureFreshAccountToken-->>AccountPermissionSyncer: success or failure
AccountPermissionSyncer->>AccountPermissionSyncer: classify cleanup decision
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 0954bf8. Configure here.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/backend/src/ee/tokenRefresh.ts`:
- Around line 307-343: The retry loop around the token refresh fetch must not
replay refresh grants once the request may have reached the provider. Update the
error classification/control flow near classifyTokenRefreshFetchError and the
retry condition to retry only failures known to occur before request
transmission; propagate timeout, connection, or response-uncertainty errors
without retrying, especially for gitlab and bitbucket-cloud. Preserve retries
for definitively pre-request failures and the existing final-error behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: a60b0bd5-6143-4051-b1d3-8b4f79064f11
📒 Files selected for processing (5)
CHANGELOG.mdpackages/backend/src/ee/accountPermissionSyncer.test.tspackages/backend/src/ee/accountPermissionSyncer.tspackages/backend/src/ee/tokenRefresh.test.tspackages/backend/src/ee/tokenRefresh.ts
Classify OAuth token refresh failures so transient provider outages are retried without clearing cached permissions, while invalid_grant remains fail-closed. Fixes SOU-1560 Fixes SOU-1177
0954bf8 to
4d6cdd0
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@CHANGELOG.md`:
- Around line 16-17: Remove the duplicate “### Fixed” heading in CHANGELOG.md
and place the OAuth token refresh bullet under the existing Fixed section,
preserving the bullet text and ordering.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 8dfa707a-8015-4311-aa13-c4681ea98667
📒 Files selected for processing (5)
CHANGELOG.mdpackages/backend/src/ee/accountPermissionSyncer.test.tspackages/backend/src/ee/accountPermissionSyncer.tspackages/backend/src/ee/tokenRefresh.test.tspackages/backend/src/ee/tokenRefresh.ts

Classify OAuth token refresh failures so transient provider outages are retried without clearing cached permissions, while invalid_grant remains fail-closed.
Fixes SOU-1560
Fixes SOU-1177
Stack created with GitHub Stacks CLI • Give Feedback 💬
Note
Medium Risk
Changes when cached repository permissions are cleared vs retained during permission sync failures, which directly affects EE access control until the next successful sync.
Overview
Fixes account permission sync wiping cached repo permissions whenever token refresh failed. Refresh errors are now classified instead of treating every refresh failure as fail-closed.
Token refresh (
tokenRefresh.ts) throws typedTokenRefreshErrorvalues (e.g.invalid_grant/ GitHubbad_refresh_token→refresh_token_rejected; 5xx, timeouts,server_error→transientwith up to 3 retries). Failures no longer collapse to a generic error that always triggered permission cleanup.Permission sync (
accountPermissionSyncer.ts) usesclassifyPermissionSyncFailure: clear permissions only for rejected refresh tokens or code-host API 401/403/410; preserve permissions for transient outages, misconfiguration, and other non-auth failures (including token-endpoint 401 that is classified as configuration, not API unauthorized).Vitest coverage was added for classification and refresh behavior; CHANGELOG notes the EE fix.
Reviewed by Cursor Bugbot for commit 27d517b. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by CodeRabbit
invalid_grantand HTTP 401/403/410), using consistent failure classification.